#include "usart.h"
#include "nvic.h"
#include <stdio.h>
#include <string.h>

/**
 * @brief       串口X初始化函数
 * @param       sclk: 串口X的时钟源频率(单位: MHz)
 *              串口1 和 串口6 的时钟源来自: rcc_pclk2 = 84Mhz
 *              串口2 - 5 / 7 / 8 的时钟源来自: rcc_pclk1 = 42Mhz
 * @note        注意: 必须设置正确的sclk, 否则串口波特率就会设置异常.
 * @param       baudrate: 波特率, 根据自己需要设置波特率值
 * @retval      无
 */
void usart_init(uint32_t sclk, uint32_t baudrate)
{
    uint32_t temp;
    /* IO 及 时钟配置 */
    RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN; /* 使能串口IO引脚时钟 */
    RCC->APB2ENR |= RCC_APB2ENR_USART1EN; /* 使能串口时钟 */
    /* 串口IO引脚 模式设置 */
    GPIOA->MODER &= ~(GPIO_MODER_MODER9_Msk|GPIO_MODER_MODER10_Msk);
    GPIOA->MODER |= (GPIO_MODER_MODE9_1|GPIO_MODER_MODE10_1);
    GPIOA->OTYPER &= ~(GPIO_OTYPER_OT9_Msk|GPIO_OTYPER_OT10_Msk);
    GPIOA->OSPEEDR &= ~(GPIO_OSPEEDR_OSPEED9_Msk|GPIO_OSPEEDR_OSPEED10_Msk);
    GPIOA->OSPEEDR |= (GPIO_OSPEEDR_OSPEED9_0|GPIO_OSPEEDR_OSPEED9_1|GPIO_OSPEEDR_OSPEED10_0|GPIO_OSPEEDR_OSPEED10_1);
    GPIOA->PUPDR &= ~(GPIO_PUPDR_PUPD9_Msk|GPIO_PUPDR_PUPD10_Msk);
    GPIOA->PUPDR |= (GPIO_PUPDR_PUPD9_0|GPIO_PUPDR_PUPD10_0);
    /* 复用功能选择 AF7 */
    GPIOA->AFR[1] &= ~(GPIO_AFRH_AFRH1|GPIO_AFRH_AFRH2);
    GPIOA->AFR[1] |= (GPIO_AFRH_AFRH1_0|GPIO_AFRH_AFRH1_1|GPIO_AFRH_AFRH1_2|GPIO_AFRH_AFRH2_0|GPIO_AFRH_AFRH2_1|GPIO_AFRH_AFRH2_2);

    temp = (sclk * 1000000 + baudrate / 2) / baudrate;              /* 得到USARTDIV@OVER8 = 0, 采用四舍五入计算 */
    /* 波特率设置 */
    USART_UX->BRR = temp;       /* 波特率设置@OVER8 = 0 */
    USART_UX->CR1 = 0;          /* 清零CR1寄存器 */
    USART_UX->CR1 |= 0 << 12;   /* 设置M = 0, 选择8位字长 */
    USART_UX->CR1 |= 0 << 15;   /* 设置OVER8 = 0, 16倍过采样 */
    USART_UX->CR1 |= 1 << 3;    /* 串口发送使能 */
#if USART_EN_RX  /* 如果使能了接收 */
    /* 使能接收中断 */
    USART_UX->CR1 |= 1 << 2;    /* 串口接收使能 */
    USART_UX->CR1 |= 1 << 5;    /* 接收缓冲区非空中断使能 */
    sys_nvic_init(3, 3, USART_UX_IRQn, 2); /* 组2，最低优先级 */
#endif
    USART_UX->CR1 |= 1 << 13;   /* 串口使能 */
}

#if USART_EN_RX     /* 如果使能了接收 */
/* 接收缓冲, 最大USART_REC_LEN个字节. */
uint8_t g_usart_rx_buf[USART_REC_LEN];
/*  接收状态
 *  bit15，      接收完成标志
 *  bit14，      接收到0x0d
 *  bit13~0，    接收到的有效字节数目
*/
uint8_t g_usart_rx_sta = 0;
/**
 * @brief       串口X中断服务函数
 * @param       无
 * @retval      无
 */
void USART_UX_IRQHandler(void) {
    uint8_t rxdata;
    if (USART_UX->SR & (1 << 5)) {               /* 接收到数据 */
        rxdata = USART_UX->DR;
        g_usart_rx_buf[g_usart_rx_sta & 0X3FFF] = rxdata;   /* 存储数据到 g_usart_rx_buf */
        g_usart_rx_sta++;
        if (g_usart_rx_sta > (USART_REC_LEN - 1))g_usart_rx_sta = 0;/* 接收数据溢出, 重新开始接收 */
    }
}
#endif

void uartProc(uint32_t currentTick) {
    static uint32_t oldTick = 0;
    if(currentTick - oldTick > 200) {
        if(g_usart_rx_sta) {
            /* 串口接收数据开始 */
            printf("%s\n",g_usart_rx_buf);

            /* 串口接收数据结束 */
            memset(g_usart_rx_buf,0,(g_usart_rx_sta+1));
            g_usart_rx_sta = 0;
        }
        oldTick = currentTick;
    }
}
